/*
Metakosmos
2011 Chad McKinney with Curtis McKinney and Cole Ingraham, as Glich Lich
A piece using a metaverse of SuperCollider tweets.

Metakosmos.new;
*/

/*
MetaLogic is the main hub for logical interactions with the dictionary of tweet keys and function strings. It controls playback and also serves as the glue between the GUI and the OSC networking.
*/
MetaLogic {
	
	classvar <tweetDict,<tweetOrderArray,currentTweets,ampNodes,ampSynth,<>reserveArray,<>activeArray;
	var node,server,<>initFlag,<>mMetaOSC,<>mMetaGUI;
	
	// MetaLogic constructor
	*new {
		^super.new.init;
	}
	
	init {
		server = server ? Server.default;
		this.setUp;
	}
	
	setUp {
		// Use for setting up the network arguments upon initialization. This prevents duplicate init processes from clients
		initFlag = 0;
		// Array of currently playing tweets. This could contain a Synth, Pattern, Array, or even an Integer
		currentTweets = [];
		//ampSynth = Synth.after(server,\MetaAmpSynth);
		node = Node.basicNew(server,1);
		MetaLogic.compileTweets;
		// Array representing the list of reserveSynths (their indexes mirror the tweetOrderArray) and their status as present or not
		reserveArray = Array.fill(MetaLogic.tweetOrderArray.size, 1 );
		// Array of tweetOrderArray indexes that represents the current active tweets
		activeArray = Array.fill(MetaLogic.tweetOrderArray.size, 1 );
		
		// This array keeps track of the state of all the tweets with [ ReverseBool, ActiveBool ]. By default all tweets are [1,0], which is to say in reserve and not active
		//tweetStateArray = Array.fill(MetaLogic.tweetOrderArray.size,{ [1,0] });
	
	}
	
	// Reset the logic, networking, and GUI
	reset {
		this.stopTweets;
		this.setUp;
		mMetaGUI.reset;
		mMetaOSC.clear;
		mMetaOSC.trySetup;
	}
	
	// Attempt to stop all sound and clean up after our tweet
	stopTweets {
		
		currentTweets.do{
			|item|
			if(item.class != Array,
			{
				this.stopTweetItem(item);
			},
			{
				currentTweets.collect{
					|subItem|
					this.stopTweetItem(subItem);
				}
			});
		};
		
		node.release(0.026); 
		node = Node.basicNew(server,1);
		currentTweets = [];
	}
	
	// Stop a single tweet item. This needs to be a separate method so we can iterate over arrays
	stopTweetItem {
		|tweet|
		var synthHolder;
		
		case
		// If the current tweet is nothing, don't do anything.
		{ tweet == nil } { 
			
		}
		
		// If The current tweet is a Synth, release the base Node
		{ tweet.class == Synth } { 
			synthHolder = tweet;
			currentTweets.release(0.025);
			// In case releasing doesn't work we can just free it
			{ 
				0.11.wait; 
				if(synthHolder != nil,
				{ 
					synthHolder.free;
				}) 
			}.fork;
		}
		
		// If the current tweet is a EventStream or Routine,
		{ tweet.class == EventStreamPlayer || tweet.class == Routine } { 
			tweet.stop; 
		}
		
		// If the current tweet was an integer, than something was scheduled likely
		{ tweet == Integer } { 
			SystemClock.clear;
			AppClock.clear;
		}
		
		// If the current tweet is something else, just nuke it....
		{ tweet != nil } { 
			CmdPeriod.run;
			//ampSynth = Synth.after(server,\MetaAmpSynth);
		};
	}
	
	// Play a tweet and add it to the tweet array
	playTweet { 
		|key,action="mono"|
		
		if(action=="mono",
		{ 
			this.stopTweets;
			{ mMetaGUI.removeAllActive; }.defer;
		});
				
		currentTweets = currentTweets.add(tweetDict[key][0].interpret);
		//ampSynth.set(\amp,tweetDict[key][1]);
		("["++key++","++tweetDict[key][1]++"]"++"\n").postln;
	}
	
	// Send the tweet over the network, making it active, and removing it from the reserveDictionary
	sendTweet {
		|id=0,action="mono"|
		
		//var actionNum;
		
		this.playTweet(tweetOrderArray[id],action);
		
		//reserveArray[index] = 0;
		reserveArray[id] = 0;
		
		// Mono = 0, Poly = 1
		if(action == "mono",
		{ 
			//actionNum = 0;
			// Iterate through the active array, if an item is active set the state to 0 and send it to the network
			activeArray.collect {
				|activeItem,index|
				if(activeItem == 1, { 
					mMetaOSC.sendTweetActiveState(index,0);
					activeArray[index] = 0;
				});
			};
			
			activeArray[id] = 1; 
		},{ 
			//actionNum = 1;
			activeArray[id] = 1;
		});
	
		//mMetaOSC.addActive(tweetOrderArray[index].asString,index);
		//mMetaOSC.sendActiveArray(activeArray);
		//mMetaOSC.removeReserve(id);
		mMetaOSC.sendReserveArray(reserveArray);
		mMetaOSC.sendActiveArray(activeArray);
	}
	
	syncTweetReserveState {
		|id,state|
		
		// If network item = 0 and local value = 1, we need to remove the reserve 
		if((state == 0) && (reserveArray[id] == 1),
		{
			{ mMetaGUI.removeReserve(tweetOrderArray[id],id); }.defer;
		});
		
		// If network item = 1 and local value = 0, we need to add it back because a packet we sent got dropped in the network
		if( (state == 1) && (reserveArray[id] == 0),{ 
			{ mMetaGUI.addReserve(tweetOrderArray[id],id); }.defer;
		});
	}
	
	
	// Parse the reserve array on the server, and sync up the discrepencies
	// NEED TO ADD GUI SYNC UPDATES
	syncReserveArray {
		|syncArray|
		syncArray.size;
		syncArray.collect {
			|item,index|			
			this.syncTweetReserveState(index,item);
		};
		
		reserveArray = syncArray;
	}
	
	// Parse the active array on the server, and sync up the discrepencies
	// NEED TO ADD GUI SYNC UPDATES 
	syncActiveArray {
		|syncArray|
		var syncActiveIndexes,localActiveIndexes;
		//"SYNC ARRAY SIZE".postln;
		//syncArray.size.postln;
		
		syncActiveIndexes = [];
		localActiveIndexes = [];
		
		syncArray.collect {
			|item,index|
			if(item == 1,
			{ 
				syncActiveIndexes = syncActiveIndexes.add(index) 
			});
		};
		
		syncActiveIndexes = syncActiveIndexes.sort;
		
		activeArray.collect {
			|item,index|
			if(item == 1,{ 
				localActiveIndexes = localActiveIndexes.add(index) 
			});	
		};
		
		localActiveIndexes = localActiveIndexes.sort;
		
		if( syncActiveIndexes == localActiveIndexes,
		{
			// Do nothing
		},{
			// Otherwise we need to make some changes
			
			// If we have less in the sync array, we're going to nuke what is currently playing and one by one add the sync array tweets
			if(syncActiveIndexes.size <= localActiveIndexes.size,
			{
				
				syncActiveIndexes.collect{
					|item,index|
					
					// The first tweet needs to be mono to kill the others
					if(index == 0,
					{
						this.playTweet(tweetOrderArray[item],"mono");
						{
							mMetaGUI.removeAllActive;
							mMetaGUI.makeActive(tweetOrderArray[item],item);
						}.defer
					},{
						this.playTweet(tweetOrderArray[item],"poly");
						{ mMetaGUI.makeActive(tweetOrderArray[item],item); }.defer;
					});	
				}
			},{
				
					syncActiveIndexes.collect{
						|item,index|
						if( localActiveIndexes.includes(item) == false,
						{
							this.playTweet(tweetOrderArray[item],"poly");
							{ mMetaGUI.makeActive(tweetOrderArray[item],item); }.defer;
						});
					}
			});
			
			activeArray = syncArray;
		});
		
	}
	
	// Iterate through the sync array, destroying the local activeArray and 
	iterateSyncArray {
		|syncArray|
		
		syncArray.collect {
			|item,index|
			if(activeArray.includes(item) == false,{ 
				
				if(index == 0,
				{ 
					this.playTweet(tweetOrderArray[index], "mono");
				},{
					this.playTweet(tweetOrderArray[index], "poly");
				});
				
				{ mMetaGUI.makeActive(tweetOrderArray[item],item); }.defer;
				
			});	
		}
	}
	
	
	// Set the state of a single tweet. [ ReserveState , ActiveState ]. A nil in either index won't set that state
	setTweetState { 
		|id=0,reserveState=0,activeState=0|
		reserveArray[id] = reserveState;
		activeArray[id] = activeState;
	}
	
	exit {
		this.stopTweets;
		mMetaOSC.reset;
		mMetaOSC.flush;	
	}		
	
	
	// Compile the source code for all the tweets and set the order
	*compileTweets {
		
		// This array is used to roughly dictate the structure of the piece, also used to translate argument index numbers from the network into tweet dictionary keys
		tweetOrderArray = [
			'Construction #1 (Chrono Crisis)',
			'Construction #2 (Salvia Dream)',
			'Construction #3 (Infinite Oculus)',
			'Construction #4 (Quest to the Infinite Tower: Sleep and Save)',
			'Construction #5 (Shifting Resonance Of the Future Shadow)',
			'Construction #6 (Karl)',
			'Construction #7 (Endless Waltz)',
			'Construction #8 (Mutagenic Growth)',
			'Construction #10 (Moon O))) )',
			'Construction #11 (Quest to the Infinite Tower: The Journey Begins)',
			'Construction #13 (Crappy Drums!)',
			'Construction #14 (Roscoe)',
			'Construction #14.5 (Aliasing Retina) ',
			'Construction #15 (Fermentation is fucking crazy if you think about it)',
			'Construction #16 (Digital Ooze)',
			'Construction #17 (Impossible Geometry)',
			'Crunch Fest',
			'Resonant Jitter',
			'Crackle Storm',
			'Glitch Bubbles',
			'A Conversation Between Electrons',
			'Atari Automatons',
			'Dragon Quest Slime',
			'Undead Dawn',
			'Pixel Hell',
			'Panopticon Rhythmicon',
			'Gamera Time Shift',
			'Chaos Is The New Sadness',
			'Electric Swamp',
			'Sun Sacrifice',
			'Dark Heart of Darkness',
			'Zombie Webern',
			'Drunk on Radon',
			'Final Boss, FIGHT!',
			'Binaural Batwings',
			'Cloud Machine Interference',
			'Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob',
			'Digital Little Doggies',
			'Trilobytes',
			'A New Low',
			'My Die Monk',
			'Fire Cat Time Spring ',
			'Kirbys Epic Yarn',
			'Cyber Zombie',
			'Poison Mushroom',
			'Vampyre Byte',
			'Construction #12 (Nano-Kitties)',
			'Broken Beat',
			'Construction #9 (Quest to the Infinite Tower: Final Battle)',
			'Voltron Style',
			'NES ATTACK'
		];
		
		("Number Of Tweets: "++tweetOrderArray.size).postln;
				
		// Add tweets to the tweetDict with Key<Symbol>,Item<[tweetStringEditedForVolume,originalTweetString]>
		tweetDict = Dictionary[
			'Construction #1 (Chrono Crisis)'->
			["play{z=LFTri.ar(0.01);m=Pulse.ar([6,4],0.1*z,200*z);GVerb.ar(BPF.ar(SinOsc.ar(([1,2,9,12]*200)+m,0,0.1+(z*0.1)).sum,m.abs*0.1+10,0.5),10)*3}",
			"play{z=LFTri.ar(0.01);m=Pulse.ar([6,4],0.1*z,200*z);GVerb.ar(BPF.ar(SinOsc.ar(([1,2,9,12]*200)+m,0,0.1+(z*0.1)).sum,m.abs*0.1+10,0.5),10)}"],
			'Construction #2 (Salvia Dream)'->
			["play{z=[0,0];10.do{m=LFNoise2.ar(Rand(0.1,1),500).abs;f=Formant.ar(m.round(35),m*2,m*4);z=z+DelayC.ar(f+z,2,[1,2])+f};z*0.001;}",
			"play{z=[0,0];10.do{m=LFNoise2.ar(Rand(0.1,1),500).abs;f=Formant.ar(m.round(35),m*2,m*4);z=z+DelayC.ar(f+z,2,[1,2])+f};z*0.001;}"],
			'Construction #3 (Infinite Oculus)'->
			["play{a=[0,2,3,7,8]+60;o=0;{o=o+LFCub.ar(a.choose.midicps,0,Decay2.ar(CoinGate.ar([1,1]*0.1,Saw.ar(4)),0.1,0.4))}!15;GVerb.ar(o*0.009,200)}",
			"play{a=[0,2,3,7,8]+60;o=0;{o=o+LFCub.ar(a.choose.midicps,0,Decay2.ar(CoinGate.ar([1,1]*0.1,Saw.ar(4)),0.1,0.4))}!15;GVerb.ar(o*0.009,200)}"],
			'Construction #4 (Quest to the Infinite Tower: Sleep and Save)'->
			["a=[52,53,55,64,57,60].midicps;i=0;r{loop{play{LFPar.ar(a[i%5])+LFPar.ar([a[i+2%5]*2,a[i+3%6]*4])*Line.kr(2,0,3,0.2)};i=i+1;2.wait}}.play",
			"a=[52,53,55,64,57,60].midicps;i=0;r{loop{play{LFPar.ar(a[i%5])+LFPar.ar([a[i+2%5]*2,a[i+3%6]*4])*Line.kr(1,0,3,0.2)};i=i+1;2.wait}}.play"],
			'Construction #5 (Shifting Resonance Of the Future Shadow)'->
			["20.do({play{GVerb.ar(BPF.ar(Blip.ar([5.rand,5.rand]*50,50,9),Rand(10,1000).round(50),0.01)*SinOsc.ar(Rand(0.01,0.1),Rand(0,2pi)),300,20)/2}})",
			"20.do({play{GVerb.ar(BPF.ar(Blip.ar([5.rand,5.rand]*50,50,9),Rand(10,1000).round(50),0.01)*SinOsc.ar(Rand(0.01,0.1),Rand(0,2pi)),300,20)}})"],
			'Construction #6 (Karl)'->
			["2.do({Pbind(\\degree,Prand((0..8)-7,inf),\\dur,Prand([1,2,4]*1,inf),\\out,9).play});play{GVerb.ar((In.ar(9,2)*100).clip2,300)}",
			"2.do({Pbind(\\degree,Prand((0..8)-7,inf),\\dur,Prand([1,2,4]*1,inf),\\out,9).play});play{GVerb.ar((In.ar(9,2)*100).clip2,300)}"],
			'Construction #7 (Endless Waltz)'->
			["play{b=GVerb.ar(Blip.ar(Duty.ar(1,0,Dseq([9,0,4,7,[12,5],16]+51,inf)).midicps,LFNoise0.kr(3,11)),200);3.do({|i|b=DelayC.ar(b*0.2,3,i)+b});b/4}",
			"play{b=GVerb.ar(Blip.ar(Duty.ar(1,0,Dseq([9,0,4,7,[12,5],16]+51,inf)).midicps,LFNoise0.kr(3,11)),200);3.do({|i|b=DelayC.ar(b*0.2,3,i)+b});b}"],
			'Construction #8 (Mutagenic Growth)'->
			["play{o=Formant.ar([50,100],LFNoise0.kr(3,500)*Decay.ar(Impulse.ar(6)),75,0.1);6.do({o=o+DelayC.ar(PitchShift.ar(o,0.001,1.5),6,6)});o.clip2}",
			"play{o=Formant.ar([50,100],LFNoise0.kr(3,500)*Decay.ar(Impulse.ar(6)),75,0.1);6.do({o=o+DelayC.ar(PitchShift.ar(o,0.001,1.5),6,6)});o.clip2}"],
			'Construction #9 (Quest to the Infinite Tower: Final Battle)'->
			["play{f=Duty.ar([0.1,0.09],0,Dseq([0,5,4,7,Drand([12,8,10,11,4])]+72,inf)).midicps*[0.5,1];GVerb.ar(SyncSaw.ar(f,[f[1],f[0]*4])*0.1,300,1)*1.8}",
			"play{f=Duty.ar([0.1,0.09],0,Dseq([0,5,4,7,Drand([12,8,10,11,4])]+72,inf)).midicps*[0.5,1];GVerb.ar(SyncSaw.ar(f,[f[1],f[0]*4])*0.1,300,1)}"],
			'Construction #10 (Moon O))) )'->
			["play{GVerb.ar(DynKlank.ar(`[Array.rand(36,9,2500)*SinOsc.ar(0.006,pi).range(1,0),nil,[2]],Blip.ar([40,40.1],200)*0.2).softclip*0.05,300,20)*3}",
			"play{GVerb.ar(DynKlank.ar(`[Array.rand(36,9,2500)*SinOsc.ar(0.006,pi).range(1,0),nil,[2]],Blip.ar([40,40.1],200)*0.2).softclip*0.05,300,20)}"],
			'Construction #11 (Quest to the Infinite Tower: The Journey Begins)'->
			["play{Pulse.ar(Demand.ar(CoinGate.ar(0.6,Impulse.ar([8,8])),0,Dseq([0,5,[3,8],[7,10],2,8,[12,15]]+48,inf)).midicps*[0.5,1.99],0.125).sum.dup}",
			"play{Pulse.ar(Demand.ar(CoinGate.ar(0.6,Impulse.ar([8,8])),0,Dseq([0,5,[3,8],[7,10],2,8,[12,15]]+48,inf)).midicps*[0.5,1.99],0.125).sum.dup}"],
			'Construction #12 (Nano-Kitties)'->
			["{r{loop{play{e=Lag.ar(Line.ar(1,0,0.3,1,0,2));f=IRand(2,10)*100;Pan2.ar(Formant.ar(f,e*1500+100,f+200)*e*0.4,Rand(-1,1))};0.25.wait}}.play}!4",
			"{r{loop{play{e=Lag.ar(Line.ar(1,0,0.3,1,0,2));f=IRand(2,10)*100;Pan2.ar(Formant.ar(f,e*1500+100,f+200)*e,Rand(-1,1))};0.25.wait}}.play}!4"],
			'Construction #13 (Crappy Drums!)'->
			["play{i={Decay.ar(CoinGate.ar(0.7,Impulse.ar([8,8])),0.2,0.1)}!2;b=SinOsc.ar(60)*i[0];n=BrownNoise.ar*i[1];GVerb.ar(b+n*0.1,20,2).softclip}",
			"play{i={Decay.ar(CoinGate.ar(0.7,Impulse.ar([8,8])),0.2,0.1)}!2;b=SinOsc.ar(60)*i[0];n=BrownNoise.ar*i[1];GVerb.ar(b+n*0.1,20,2).softclip}"],
			'Construction #14 (Roscoe)'->
			["play{f={TIRand.ar(1,4000,Impulse.ar(12)).round(600)+1}!5;n=LFNoise0.ar(f*0.01)*8;Gendy2.ar(6,5,[n[0],n[1]],[n[2],n[3]],f[0],f[1],0.4,0.1,8)}",
			"play{f={TIRand.ar(1,4000,Impulse.ar(12)).round(600)+1}!5;n=LFNoise0.ar(f*0.01)*8;Gendy2.ar(6,5,[n[0],n[1]],[n[2],n[3]],f[0],f[1],0.4,0.1,8)}"],
			'Construction #14.5 (Aliasing Retina) '->
			["play{f={TIRand.ar(9,30000,Impulse.ar(4))}!5;n=LFCub.ar(0.07,0,0.1,0.2)%f;BMoog.ar(Gendy2.ar(6,6,[n[0],n[1]],[n[2],n[3]],f[0],f[1]),2999,0)*0.3}",
			"play{f={TIRand.ar(9,30000,Impulse.ar(4))}!5;n=LFCub.ar(0.07,0,0.1,0.2)%f;BMoog.ar(Gendy2.ar(6,6,[n[0],n[1]],[n[2],n[3]],f[0],f[1]),2999,0)}"],
			'Construction #15 (Fermentation is fucking crazy if you think about it)'->
			["play{GVerb.ar(Blip.ar([48,52,53,55,60].midicps,{SinOsc.ar(0.08,6.rand,20,20)}!5,{Decay.ar(CoinGate.ar(0.4,Pulse.ar(3)),9,0.002)}!5).sum,99)*3}",
			"play{GVerb.ar(Blip.ar([48,52,53,55,60].midicps,{SinOsc.ar(0.08,6.rand,20,20)}!5,{Decay.ar(CoinGate.ar(0.4,Pulse.ar(3)),9,0.002)}!5).sum,99)}"],
			'Construction #16 (Digital Ooze)'->
			["play{Shaper.ar(Buffer.alloc(s,512,1,{|u|u.chebyMsg([1,1])}),Blip.ar(LFNoise0.ar(9,33,33),LFNoise0.ar([8,7],60,60),LFNoise1.ar([4,3],1,1)))}",
			"play{Shaper.ar(Buffer.alloc(s,512,1,{|u|u.chebyMsg([1,1])}),Blip.ar(LFNoise0.ar(9,33,33),LFNoise0.ar([8,7],60,60),LFNoise1.ar([4,3],1,1)))}"],
			'Construction #17 (Impossible Geometry)'->
			["Ndef(\s,{n=Ndef.ar(\s);GVerb.ar(SinOsc.ar(LFNoise1.ar(0.1,200,250).round(50)*[1,1.5]+(n*30),(n*1.6),SinOsc.ar(0.1,0,1,1)),300,20)*0.1}).play",
			"Ndef(\s,{n=Ndef.ar(\s);GVerb.ar(SinOsc.ar(LFNoise1.ar(0.1,200,250).round(50)*[1,1.5]+(n*30),(n*1.6),SinOsc.ar(0.1,0,1,1)),300,20)*0.1}).play"],
			'Crunch Fest'->
			["play{n=LFNoise2.ar;p=Pulse.ar([n,n*n]);g=GVerb.ar(ArrayMin.ar([p*n*n,p/n*n]-p));ArrayMax.ar([CombN.ar(clip2(g*g,n),1,1),clip2(g,p)])}",
			"play{n=LFNoise2.ar;p=Pulse.ar([n,n*n]);g=GVerb.ar(ArrayMin.ar([p*n*n,p/n*n]-p));ArrayMax.ar([CombN.ar(clip2(g*g,n),1,1),clip2(g,p)])}"],
			'Resonant Jitter'->
			["play{z=LFTri;n=LFNoise0;g=GVerb;a=g.ar(g.ar(z.ar(n.kr([9,8],1500,1550))*n.kr(9)).distort*n.kr(8)*z.kr(9))*z.kr(n.kr([3,4],98,99));g.ar(a*a)*0.3}",
			"play{z=LFTri;n=LFNoise0;g=GVerb;a=g.ar(g.ar(z.ar(n.kr([9,8],1500,1550))*n.kr(9)).distort*n.kr(8)*z.kr(9))*z.kr(n.kr([3,4],98,99));g.ar(a*a)}"],
			'Crackle Storm'->
			["play{n=LFNoise0;p=Saw;z=LFTri;a=p.ar([z.kr(n.kr(7,97,98),3,4),z.kr(2,5,6)]);b=z.ar([91,90]);b*BPF.ar(b,z.kr(n.kr(1,8,9),90,99)).clip2}",
			"play{n=LFNoise0;p=Saw;z=LFTri;a=p.ar([z.kr(n.kr(7,97,98),3,4),z.kr(2,5,6)]);b=z.ar([91,90]);b*BPF.ar(b,z.kr(n.kr(1,8,9),90,99)).clip2}"],
			'Glitch Bubbles'->
			["play{q=SinOsc;n=CuspL;a=q.ar([n.ar(91),n.ar(89)]*200,n.ar(90)*10);b=HPF.ar(a*a,a**a);LPF.ar(b**a,a**a).fold2(0.5).distort}",
			"play{q=SinOsc;n=CuspL;a=q.ar([n.ar(91),n.ar(89)]*200,n.ar(90)*10);b=HPF.ar(a*a,a**a);LPF.ar(b**a,a**a).fold2(0.5).distort}"],
			'A Conversation Between Electrons'->
			["play{c=StandardN;l=LFNoise0;i=Dust;d=Decay2;Splay.ar(c.ar(l.kr([6,5,4]).range(1,999))*d.ar(i.ar([9,8,7])))}",
			"play{c=StandardN;l=LFNoise0;i=Dust;d=Decay2;Splay.ar(c.ar(l.kr([6,5,4]).range(1,999))*d.ar(i.ar([9,8,7])))}"],
			'Atari Automatons'->
			["play{{|i|r=LFNoise2.ar(0.3,0.5,0.5);n=DelayC.ar(In.ar(i*r),1,i);Out.ar(i*r,Ringz.ar(n+Impulse.ar(),Pitch.kr(n)[0]*i,200).softclip)}!30}",
			"play{{|i|r=LFNoise2.ar(0.3,0.5,0.5);n=DelayC.ar(In.ar(i*r),1,i);Out.ar(i*r,Ringz.ar(n+Impulse.ar(),Pitch.kr(n)[0]*i,200).softclip)}!30}"],
			'Dragon Quest Slime'->
			["play{b=LocalBuf(8192,4);d=Dust.kr(9)+Dust2.kr([4,4]);r=PlayBuf.ar(2,b,TExpRand.kr(0.01,19,d),d,0,1)/4;f=FFT(b,d+(d*r));r.clip2(1)}",
			"play{b=LocalBuf(8192,4);d=Dust.kr(9)+Dust2.kr([4,4]);r=PlayBuf.ar(2,b,TExpRand.kr(0.01,19,d),d,0,1)/4;f=FFT(b,d+(d*r));r.clip2(1)}"],
			'Undead Dawn'->
			["play{i=Impulse.kr([4,1]).sum;f=TIRand.kr(2,30,CoinGate.kr(0.07,i))*30;GVerb.ar(Formant.ar(30,60,Lag.kr(f,1))*Decay2.kr(i,0.1,1),300,3)*2.4}",
			"play{i=Impulse.kr([4,1]).sum;f=TIRand.kr(2,30,CoinGate.kr(0.07,i))*30;GVerb.ar(Formant.ar(30,60,Lag.kr(f,1))*Decay2.kr(i,0.1,1),300,3)}"],
			'Pixel Hell'->
			["play{b=LocalBuf(1);y=Dbufwr(Dbufrd(b).fold2+CombC.ar(Pulse.ar(LFNoise0.ar([7,7],99)),1,5e-05),b);LeakDC.ar(Duty.ar(1/SampleRate.ir,0,y))*0.1}",
			"play{b=LocalBuf(1);y=Dbufwr(Dbufrd(b).fold2+CombC.ar(Pulse.ar(LFNoise0.ar([7,7],99)),1,5e-05),b);LeakDC.ar(Duty.ar(1/SampleRate.ir,0,y))}"],
			'Panopticon Rhythmicon'->
			["r{loop{play{f=IRand([1,1],10)*40;p=Pulse.ar(f/128)/9;RLPF.ar(DelayC.ar(p,2,1.25)+p,f,0.001)*Line.kr(0.3,0,30.rand+9,1,0,2)*1.5};2.5.wait}}.play",
			"r{loop{play{f=IRand([1,1],10)*40;p=Pulse.ar(f/128)/9;RLPF.ar(DelayC.ar(p,2,1.25)+p,f,0.001)*Line.kr(0.3,0,30.rand+9,1,0,2)};2.5.wait}}.play"],
			'Gamera Time Shift'->
			["a=[67,60,67,72,65,61,68,48,61].midicps/2;play{i=AllpassC.ar(Pulse.ar(LFPulse.ar(0.3).dup));Pluck.ar(i,i,1,1/Demand.ar(i,0,Dseq(a,inf)),99)/2}",
			"a=[67,60,67,72,65,61,68,48,61].midicps/2;play{i=AllpassC.ar(Pulse.ar(LFPulse.ar(0.3).dup));Pluck.ar(i,i,1,1/Demand.ar(i,0,Dseq(a,inf)),99)}"],
			'Chaos Is The New Sadness'->
			["play{r=SampleRate.ir;n=LocalIn.ar(2);c=HenonC.ar(r,SinOsc.ar(Pitch.kr(n)),n);l=LocalOut.ar(DelayC.ar(c));CombC.ar(c,1,0.2,1)}",
			"play{r=SampleRate.ir;n=LocalIn.ar(2);c=HenonC.ar(r,SinOsc.ar(Pitch.kr(n)),n);l=LocalOut.ar(DelayC.ar(c));CombC.ar(c,1,0.2,1)}"],
			'Electric Swamp'->
			["play{c=HenonN.ar(40,LFNoise2.ar(0.5),LFNoise2.ar([0.2,0.2]));Decay.ar(RLPF.ar(Impulse.ar(20),c*SampleRate.ir*2,0.0001).clip2(0.25),2)}",
			"play{c=HenonN.ar(40,LFNoise2.ar(0.5),LFNoise2.ar([0.2,0.2]));Decay.ar(RLPF.ar(Impulse.ar(20),c*SampleRate.ir*2,0.0001).clip2(0.5),2)}"],
			'Sun Sacrifice'->
			["play{g=DelayC.ar(LocalIn.ar(2),1,1/3.75)+Gendy1.ar(6,6,[1,1],1,0);l=LocalOut.ar(g);Ringz.ar(LeakDC.ar(g)*2,[416,423]+(g*2),1).softclip}",
			"play{g=DelayC.ar(LocalIn.ar(2),1,1/3.75)+Gendy1.ar(6,6,[1,1],1,0);l=LocalOut.ar(g);Ringz.ar(LeakDC.ar(g)*2,[416,423]+(g*2),1).softclip}"],
			'Dark Heart of Darkness'->
			["play{e=Integrator.ar(LocalIn.ar(2)+Pulse.ar(9,[0.25,0.75]),0.001);LocalOut.ar(DelayC.ar(e*0.99,1,1/TRand.kr(1,60,Dust.kr(1/2))));e.softclip}",
			"play{e=Integrator.ar(LocalIn.ar(2)+Pulse.ar(9,[0.25,0.75]),0.001);LocalOut.ar(DelayC.ar(e*0.99,1,1/TRand.kr(1,60,Dust.kr(1/2))));e.softclip}"],
			'Zombie Webern'->
			["a=(1..12);play{CombN.ar(Pulse.ar(XLine.kr(1,99,60),0.01)*2,1,1/(Demand.ar(Impulse.ar(1.5),0,Dshuf(a,inf)).midicps*[8,4]),2).trunc(0.5**8)*0.4}",
			"a=(1..12);play{CombN.ar(Pulse.ar(XLine.kr(1,99,60),0.01)*2,1,1/(Demand.ar(Impulse.ar(1.5),0,Dshuf(a,inf)).midicps*[8,4]),2).trunc(0.5**8)}"],
			'Drunk on Radon'->
			["play{r=SampleRate.ir;c=CuspN.ar([5,4]);CombN.ar(SinOsc.ar(SinOsc.ar(1/2,c.abs,c*r,c*r)*LFNoise2.ar(0.5).abs),1,1/(c.abs*32),Lag.ar(c*2))}",
			"play{r=SampleRate.ir;c=CuspN.ar([5,4]);CombN.ar(SinOsc.ar(SinOsc.ar(1/2,c.abs,c*r,c*r)*LFNoise2.ar(0.5).abs),1,1/(c.abs*32),Lag.ar(c*2))}"],
			'Final Boss, FIGHT!'->
			["a=[1,2,5,6,9,8,11,10,4,4].midicps;a=a++(a*2)++(a*4);play{t=Impulse.ar(0.5);d=Demand.ar(t,0,Dseq(a,inf));Pulse.ar([d*2,d*3],Decay.ar(t,3))}",
			"a=[1,2,5,6,9,8,11,10,4,4].midicps;a=a++(a*2)++(a*4);play{t=Impulse.ar(0.5);d=Demand.ar(t,0,Dseq(a,inf));Pulse.ar([d*2,d*3],Decay.ar(t,3))}"],
			'Binaural Batwings'->
			["play{t=LFPulse.ar(7.5,[0,0.5]);f=Phasor.kr(0,XLine.kr(1664,7.5,30),1.625,26624);Limiter.ar(CombC.ar(Ringz.ar(t,f,1/7.5),1,1/13,2),0.9)}",
			"play{t=LFPulse.ar(7.5,[0,0.5]);f=Phasor.kr(0,XLine.kr(1664,7.5,30),1.625,26624);Limiter.ar(CombC.ar(Ringz.ar(t,f,1/7.5),1,1/13,2),0.9)}"],
			'Cloud Machine Interference'->
			["play{d=Duty.kr(Dwhite(0,LFNoise2.ar([1,1]).abs,inf),0,Dwhite(0,230,inf));GVerb.ar(BPF.ar(PinkNoise.ar(39),d.midicps,0.005).softclip,2,0.05)/2}",
			"play{d=Duty.kr(Dwhite(0,LFNoise2.ar([1,1]).abs,inf),0,Dwhite(0,230,inf));GVerb.ar(BPF.ar(PinkNoise.ar(39),d.midicps,0.005).softclip,2,0.05)}"],
			'Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob Wob'->
			["play{t=Impulse.ar(2/3);f=Demand.ar(t,0,Dseq([5,10,9,4,4,14,4,8],inf).midicps)*4;Limiter.ar(SinOsc.ar([f,f],0,2).distort*3*LFTri.ar(3).abs)}",
			"play{t=Impulse.ar(2/3);f=Demand.ar(t,0,Dseq([5,10,9,4,4,14,4,8],inf).midicps)*4;Limiter.ar(SinOsc.ar([f,f],0,2).distort*3*LFTri.ar(3).abs)}"],
			'Digital Little Doggies'->
			["play{p=Impulse.ar(2,[1/3,0]);d=Demand.ar(p,0,Dseq([0,4,7,4,1,4,7,4,2,5,7,5,2,5,7,5],inf)).midicps*16;Pluck.ar(PinkNoise.ar,p,1,1/d,3).sum*2}",
			"play{p=Impulse.ar(2,[1/3,0]);d=Demand.ar(p,0,Dseq([0,4,7,4,1,4,7,4,2,5,7,5,2,5,7,5],inf)).midicps*16;Pluck.ar(PinkNoise.ar,p,1,1/d,3).sum}"],
			'Trilobytes'->
			["play{i=Impulse;p=i.ar([1.5,1.875])+i.ar([2.5,2])+i.ar(3);d=Demand.ar(p,0,Dseq([4,5,2,7,9,2,1,4,5,8,10]*50,inf));RLPF.ar(p*13,d,0.025)*0.6}",
			"play{i=Impulse;p=i.ar([1.5,1.875])+i.ar([2.5,2])+i.ar(3);d=Demand.ar(p,0,Dseq([4,5,2,7,9,2,1,4,5,8,10]*50,inf));RLPF.ar(p*13,d,0.025)}"],
			'A New Low'->
			["play{t=Saw.ar(4,0.5,0.5);f=Duty.ar(3.75,0,Dseq([3.5,2,3.15,2.33],inf))*20;Limiter.ar(MoogFF.ar(Saw.ar(1/4)+Pulse.ar([f,f*3/2]),f*t*16,0.3))}",
			"play{t=Saw.ar(4,0.5,0.5);f=Duty.ar(3.75,0,Dseq([3.5,2,3.15,2.33],inf))*20;Limiter.ar(MoogFF.ar(Saw.ar(1/4)+Pulse.ar([f,f*3/2]),f*t*16,0.3))}"],
			'My Die Monk'->
			["Pbind(\\instrument,play{|freq|SyncSaw.ar(3,freq,[0.3,0.3])}.defName,\\scale,[0,1,4,5,7,8,10,11],\\degree,Pbrown(-9,26,4),\\dur,Pbrown(0.5,4,0.5)/30).play",
			"Pbind(\\instrument,play{|freq|SyncSaw.ar(3,freq)}.defName,\\scale,[0,1,4,5,7,8,10,11],\\degree,Pbrown(-9,26,4),\\dur,Pbrown(0.5,4,0.5)/30).play"],
			'NES ATTACK'->
			["{|i|Pbind(\\instrument,play{|freq|LFNoise0.ar([freq,freq])/2.5}.defName,\\legato,0.35,\\scale,(1..9),\\degree,Pbrown(0,79,8),\\dur,i+1/9).play}!8",
			"{|i|Pbind(\\instrument,play{|freq|LFNoise0.ar([freq,freq])/2}.defName,\\legato,0.35,\\scale,(1..9),\\degree,Pbrown(0,79,8),\\dur,i+1/9).play}!8"],
			'Fire Cat Time Spring '->
			["play{n=LocalIn.ar(2);o=SinOsc.ar(Pitch.kr(n,40,10)[0]+Spring.ar(n,20),Spring.ar(n,5));l=LocalOut.ar(Decay2.ar(Dust.ar(0.3),0.1,10)*o);o}",
			"play{n=LocalIn.ar(2);o=SinOsc.ar(Pitch.kr(n,40,10)[0]+Spring.ar(n,20),Spring.ar(n,5));l=LocalOut.ar(Decay2.ar(Dust.ar(0.3),0.1,10)*o);o}"],
			'Voltron Style'->
			["play{t=Impulse.ar(4.5,[0,0.5]);f=Demand.ar(CoinGate.ar(0.1,t[0]),0,Dseq([0,5,4,7,1,8,12]+36,inf)).midicps;SyncSaw.ar(9,[f,f*2])*Decay.ar(t)*0.65}",
			"play{t=Impulse.ar(4.5,[0,0.5]);f=Demand.ar(CoinGate.ar(0.1,t[0]),0,Dseq([0,5,4,7,1,8,12]+36,inf)).midicps;SyncSaw.ar(9,[f,f*2])*Decay.ar(t)}"],
			'Kirbys Epic Yarn'->
			["b=Buffer.alloc(s,44100,1,{|u|u.chebyMsg(Array.fill(1028,{2.rand}))});play{Shaper.ar(b,Osc.ar(b,0.004*Stepper.ar(Pulse.ar([4,3]),0,0,9)))}",
			"b=Buffer.alloc(s,44100,1,{|u|u.chebyMsg(Array.fill(1028,{2.rand}))});play{Shaper.ar(b,Osc.ar(b,0.004*Stepper.ar(Pulse.ar([4,3]),0,0,9)))}"],
			'Cyber Zombie'->
			["play{Shaper.ar(Buffer.alloc(s,44100).cheby(Array.fill(512,{2.rand})),LFSaw.ar(1,[0,1])*1.5*Saw.ar(LFNoise0.ar(0.25.dup,49,59)))}",
			"play{Shaper.ar(Buffer.alloc(s,44100).cheby(Array.fill(512,{2.rand})),LFSaw.ar(1,[0,1])*1.5*Saw.ar(LFNoise0.ar(0.25.dup,49,59)))}"],
			'Poison Mushroom'->
			["play{SyncSaw.ar([3,4],Duty.ar(1/Dstutter(60,Dwhite(5,159)),0,Dseries(0,Dstutter(60,Dwhite(-330,9)/300))%1).linexp(0,1,20,3000)).trunc(0.25)}",
			"play{SyncSaw.ar([3,4],Duty.ar(1/Dstutter(60,Dwhite(5,159)),0,Dseries(0,Dstutter(60,Dwhite(-330,9)/300))%1).linexp(0,1,20,3000)).trunc(0.25)}"],
			'Broken Beat'->
			["play{CombC.ar(BPF.ar(WhiteNoise.ar,Duty.ar(Diwhite(1,2)/4,[0,0],Dseries(0,Dstutter(9,Dwhite(-9,9)))%9).linexp(0,9,30,9999),0.15,999).clip2)*0.7}",
			"play{CombC.ar(BPF.ar(WhiteNoise.ar,Duty.ar(Diwhite(1,2)/4,[0,0],Dseries(0,Dstutter(9,Dwhite(-9,9)))%9).linexp(0,9,30,9999),0.15,999).clip2)}"],
			'Vampyre Byte'->
			["Ndef(\\p,{n=Ndef.ar(\\p);Limiter.ar(AllpassN.ar(SyncSaw.ar(n,(Pitch.kr(n,3,3)[0]*2-88200).dup%88200).trunc(0.5**4),1,1/[3.25,3.35],13))}).play",
			"Ndef(\\p,{n=Ndef.ar(\\p);Limiter.ar(AllpassN.ar(SyncSaw.ar(n,(Pitch.kr(n,3,3)[0]*2-88200).dup%88200).trunc(0.5**4),1,1/[3.25,3.35],13))}).play"]
		];
		
		// Master Voume/Limiter Synth Definition
		SynthDef.new(\MetaAmpSynth,{
			|amp=1,inBus=0,gate=1|
			var signal,in,env;
			in = In.ar(inBus,2);
			env = EnvGen.ar(Env.asr(0.001,1,0.025),gate:gate,doneAction:2);
			signal = Limiter.ar(in*amp,1,0.0005)*env;
			ReplaceOut.ar(0,signal);
		}).store;	
	}

}